# 12. Cookie、Session、Token区别
# http是无状态的协议
HTTP是一种不保存状态的,无状态的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,自身不具备保存之前发送过的请求或响应信息的功能。每当有新的请求发送时,就会有对应的新响应产生。这是为了快速的处理大量事务,确保协议的可伸缩性。
至于为什么HTTP没状态,可能是因为HTTP协议设计时一是为了简单考虑二是早期没考虑到现在web发展需求这个情况。
HTTP/1.1虽然是无状态协议,但为了实现保持状态功能,于是引入了Cookie技术。
# Cookie
如果只用Cookie来识别用户状态,那么用户信息会全部保存在客户端,虽然也可以实现服务器识别用户状态,但会造成以下问题:
- 可能造成CSRF安全问题,一旦数据泄露,那么攻击者就可以伪造用户做一些危险操作。
- Cookie只有4k容量,数据量大时可能会造成空间不足,而且网络传输的数据量也会变大。
# Session
因为Cookie非常容易造成安全问题,所以就有了Session+Cookie。过程如下:
- 客户端登录时发送请求
- 服务端接收到请求验证登录通过后,建立一个sessionid随机字符串。并在响应头字段Set-Cookie中返回sessionId。Set-Cookie格式如下
Set-Cookie: sessionId:xxx
- 客户端再次发送请求时浏览器会自动在Cookie中包含sessionid发送到服务端。
- 服务端接收到请求后对比sessionid,然后获取到用户信息。
Session只需要在客户端保存一个id,实际上大量数据都是保存在服务端。禁用Cookie后还有其他方法存储,比如放在url中。会出现以下问题:
- 造成CSRF安全问题
- 用户信息全部放在服务端会造成服务器压力
# Token
因为Session+Cookie的方式会造成安全问题和可能会造成服务器压力过大的问题,就有了token。token 也称作令牌。服务端并不会保存身份认证相关的数据。
# 组成
uid: 用户唯一身份标识
time: 当前时间的时间戳
sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接
固定参数(可选): 将一些常用的固定参数加入到 token 中是为了避免重复查库
# 存放
token在客户端一般存放于localStorage,cookie,或sessionStorage中。在服务器一般存于数据库中。
# 认证流程
token 的认证流程与cookie很相似
- 用户登录,成功后服务器返回Token给客户端。
- 客户端收到数据后保存在客户端
- 客户端再次访问服务器,将token放入headers中
- 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码
token是开发者为了防范csrf而特别设计的令牌,浏览器不会自动添加到headers里,攻击者也无法访问用户的token,所以提交的表单无法通过服务器过滤,也就无法形成攻击。
# 参考
https://segmentfault.com/a/1190000017831088 (opens new window)
# 补充:Cookie、Session、Token 全面对比
在 Web 开发中,Cookie、Session、Token 是用于用户身份认证和会话管理的三种核心机制。你可以把它们想象成三种不同的“通行证”设计。
# 一、一句话理解
| 机制 | 一句话概括 | 存放位置 |
|---|---|---|
| Cookie | 浏览器里的“便签纸”,用来存少量数据(如用户 ID),每次请求自动带上 | 浏览器端 |
| Session | 服务器端的“档案柜”,存用户状态(如登录信息),通过 Session ID 查找 | 服务器端 |
| Token | 一个“加密签名令牌”,包含用户信息和有效期,服务端通过签名验证真实性 | 客户端(通常存在 localStorage 或 Cookie) |
# 二、核心原理对比
# 1. Cookie
Cookie 是浏览器自带的一种存储机制,由服务器通过 HTTP 响应头的 Set-Cookie 字段设置,浏览器会将其保存并在后续请求中自动携带。
┌─────────────┐ Set-Cookie: user_id=123 ┌─────────────┐
│ 浏览器 │ ◄────────────────────────────────────── │ 服务器 │
│ (存Cookie) │ ──────────────────────────────────────► │ (设置Cookie)│
└─────────────┘ 每次请求自动携带 Cookie └─────────────┘
2
3
4
特点:
- 自动携带:浏览器在请求同一域名时会自动带上 Cookie,不需要手动处理
- 大小限制:每个域名下最多 4KB
- 安全性:可设置 HttpOnly(禁止 JS 读取)和 Secure(仅 HTTPS 传输)
# 2. Session
Session 是服务端存储的用户状态数据。当用户登录后,服务端会创建一个 Session,生成一个唯一的 Session ID,并通过 Cookie 返回给客户端。
┌─────────────┐ Cookie: session_id=abc123 ┌─────────────┐
│ 浏览器 │ ────────────────────────────────► │ 服务器 │
│ (存Session │ ◄──────────────────────────────── │ (存用户数据)│
│ ID) │ 返回 Session 对应的数据 │ Session: │
└─────────────┘ │ {user:张三}│
└─────────────┘
2
3
4
5
6
特点:
- 服务端存储:数据存在服务器内存或 Redis 中,客户端只存一个 ID
- 状态保持:Session 有有效期,过期后自动销毁
- 安全性较高:数据在服务端,客户端无法篡改
- 缺点:分布式部署时需要共享 Session(如用 Redis 集中存储)
# 3. Token
Token 是一种自包含的加密令牌,服务端通过签名验证 Token 的合法性和有效性。最常用的是 JWT(JSON Web Token)。
┌─────────────┐ Authorization: Bearer xxx ┌─────────────┐
│ 浏览器 │ ───────────────────────────────────► │ 服务器 │
│ (存Token) │ │ (验证签名) │
└─────────────┘ ◄────────────────────────────────── └─────────────┘
返回数据 Token 合法则放行
2
3
4
5
JWT 结构:
Header.Payload.Signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMjMifQ.xxxxxx
↓ ↓ ↓
算法 用户信息 签名
2
3
4
特点:
- 无状态:服务端不需要存储 Token,验证签名即可
- 自包含:Token 里包含了用户信息(如 user_id),服务端可以直接解码使用
- 跨域友好:适合移动端和多域名场景
- 缺点:Token 一旦签发,在过期前无法主动撤销(需要额外维护黑名单)
# 三、区别对比表
| 维度 | Cookie | Session | Token (JWT) |
|---|---|---|---|
| 存储位置 | 浏览器端 | 服务器端(内存/Redis) | 客户端(localStorage/Cookie) |
| 数据大小 | ≤ 4KB | 不限(取决于服务器内存) | 较大(包含用户信息) |
| 是否状态 | 无状态(仅存数据) | 有状态(服务端存数据) | 无状态(自包含) |
| 安全性 | 低(容易被窃取) | 较高(数据在服务端) | 高(依赖签名算法) |
| 跨域支持 | 需配置 withCredentials | 需共享 Session 存储 | ✅ 天然支持 |
| 移动端支持 | ❌ 不支持(App 无浏览器 Cookie) | ❌ 不支持 | ✅ 支持 |
| 注销/登出 | 清除 Cookie | 删除服务端 Session 记录 | 清理客户端 Token(但 Token 在服务端仍有效) |
| 分布式扩展 | 简单 | 需要 Session 共享(如 Redis) | ✅ 天然支持 |
| 典型场景 | 存储小数据、跟踪会话 | Web 应用登录状态 | RESTful API、移动应用、微服务 |
# 四、三种方案的安全建议
| 机制 | 常见攻击 | 防范措施 |
|---|---|---|
| Cookie | XSS(窃取 Cookie) | 设置 HttpOnly、Secure、SameSite |
| Session | CSRF(跨站请求伪造) | 使用 CSRF Token、SameSite 属性 |
| Token | XSS(窃取 Token) | 存 httpOnly Cookie 或内存中,避免存 localStorage |
# 五、面试回答话术
Cookie、Session、Token 是 Web 开发中用于身份认证和会话管理的三种机制:
Cookie 是浏览器提供的存储机制,数据保存在客户端,每次请求会自动携带。适合存储少量数据,但需要注意安全设置,比如 HttpOnly 防止 XSS 攻击。
Session 是服务端存储的用户状态,客户端只存一个 Session ID。它的数据更安全,但在分布式环境下需要共享 Session 存储(如 Redis)。适合传统的 Web 应用。
Token(最常见的是 JWT)是一种自包含的加密令牌,包含了用户信息和签名,服务端通过验证签名来确认身份。它是无状态的,天然支持跨域和分布式场景,适合 RESTful API、移动应用和微服务架构。
三者的演进关系:
- Cookie 是最基础的存储机制
- Session 是基于 Cookie 的服务端状态管理
- Token 是更现代的、无状态的认证方案,解决了 Session 在分布式和跨域场景下的局限性
在实际项目中,我会根据业务场景选择:
- 传统的服务端渲染 Web 应用 → Session
- 前后端分离的 RESTful API → Token (JWT)
- 同时设置 httpOnly Cookie 存储 Token,兼顾安全和便利
# 六、Token 与 Session 的核心取舍
Session 模式:服务器存数据,压力在服务端
Token 模式:客户端存数据,压力在带宽和签名验证
2
- 选择 Session:如果你需要服务端主动撤销登录,且用户量可控
- 选择 Token:如果你需要跨域、移动端支持,或分布式扩展
# 七、一句话总结
Cookie 是“浏览器贴纸”,Session 是“服务器档案柜”,Token 是“带签名的电子门禁卡”。
三者常组合使用:用 Cookie 存 Session ID 或 Token,用 Session 存敏感状态,用 Token 做无状态认证。理解它们的区别和适用场景,是设计安全、可扩展的认证系统的基础。